import java.util.ArrayList;
import java.util.Observable;
import java.util.Scanner;

/**
 * Class to control the flow of a poker game
 * @author Kat Winter
 */
public class PokerTable extends Observable {
	
	private Deck cards;
	private PokerGame game;
	private Player player;
	private Player dealer;
	
	/**
	 * Sets up a new game
	 * @param numberOfPlayers Number of players in the game - right now the
	 * game only accomodates a single human player and a dealer AI player
	 */
	public void playGame(int numberOfPlayers) {
		
				// Initialize game
				game = new PokerGame();
				
				// Get a deck of cards
				cards = new Deck();
				
				// Shuffle the deck
				cards.shuffle();
				
				// Create player
				player = new Player(1);
				
				// Create AI dealer
				dealer = new Player(0);
				
				roundComplete = false;
				
				deal(cards);
	}
	
	private boolean roundComplete = false;
	int dealerCardsToSwap = 0;
	
	/**
	 * Handle the swapping of cards for the player and then
	 * set up the AI and have it swap its cards
	 * @param discardPile Boolean Array representing the cards the
	 * player wants to swap out - a True at an index means the card
	 * at the corresponding index in the player's hand should be swapped out.
	 */
	public void cardSwap(boolean[] discardPile) {
		
		int discardCount = 0;
		
		// discard unwanted cards
		for (int i = 4; i >= 0; i--) {
			if (discardPile[i]) {
				player.removeCard(i);
				discardCount++;
			}
		}
		
		// deal replacement cards
		for (int j = 0; j < discardCount; j++) {
			player.addCard(cards.remove(0));
		}
		
		// Create AI for the dealer
		PokerAI AI = new PokerAI();
		
		// AI swaps cards
		dealerCardsToSwap = AI.play(dealer);
		
		for (int swapCount = 0; swapCount < dealerCardsToSwap; swapCount++) {
			dealer.addCard(cards.remove(0));
		}
		
		// Mark the round complete
		roundComplete = true;
		
		setChanged();
		notifyObservers();
	}
	
	/**
	 * Checks if the round is over
	 * @return True if the round is complete, False if not
	 */
	public boolean roundComplete() {
		
		return roundComplete;
	}
	
	private int playerWins = 0;
	private int dealerWins = 0;
	
	/**
	 * @return "You Win" if the player wins (seat 1) or "Dealer Wins" if the dealer wins (Seat 0)
	 */
	public String getWinner() {
		
		ArrayList<Player> players = new ArrayList<Player>();
		players.add(player);
		players.add(dealer);
		
		Player winner = game.getWinner(players);
		
		if (winner.getSeat() == 0) {
			
			dealerWins++;
			return "Dealer Wins!";
		}
		
		else {
			
			playerWins++;
			return "You Win!";		
		}
	}
	
	/**
	 * @return Count of the player's wins
	 */
	public int getPlayerWins() {
		return playerWins;
	}
	
	/**
	 * @return Count of the player's losses (same as Dealer's wins)
	 */
	public int getDealerWins() {
		return dealerWins;
	}
	
	/**
	 * @return Number of cards the dealer is swapping out
	 */
	public int getSwapResults() {
		
		return dealerCardsToSwap;
	}
	
	/**
	 * @return Player representing the current human player
	 */
	public Player getPlayer() {
		return player;
	}
	
	/**
	 * @return Player representing the dealer (AI)
	 */
	public Player getDealer() {
		return dealer;
	}
	
	/**
	 * Deals out two hands of Cards from the Deck, one to the player and one
	 * to the dealer
	 * @param deck Deck of Cards from which the hands should be dealt
	 */
	private void deal(Deck deck) {
		
		// Deal player a hand of cards from the deck
			for (int iCardCount = 0; iCardCount < 5; iCardCount++) {
				player.addCard(cards.remove(0));
		}

		// Deal for the AI dealer
		for (int iCardCount = 0; iCardCount < 5; iCardCount++) {
			dealer.addCard(cards.remove(0));
		}
		
		// Notify observers that new hands have been dealt
		setChanged();
		notifyObservers();
	}
	
	/**
	 * @return String representing the result of the dealer's hand
	 */
	public String getDealerHand() {
		
		return game.evaluateHand(dealer).toString();
	}
	
	/**
	 * @return String representing the high card in the dealer's hand
	 */
	public String getDealerHighCard() {
		
		return game.getHighCard(dealer.getHand()).toString();
	}
	
	/**
	 * @return String representing the result of the player's hand
	 */
	public String getPlayerHand() {
		
		return game.evaluateHand(player).toString();
	}
	
	/**
	 * @return String representing the high card in the player's hand
	 */
	public String getPlayerHighCard() {
		
		return game.getHighCard(player.getHand()).toString();
	}
}
